#include "Inf_74HC595.h"

#define OE_PIN              FL_GPIO_PIN_6
#define SHIFT_REG_DATA_SIZE 100

static uint8_t  shiftRegData[SHIFT_REG_DATA_SIZE] = { 0 };
static uint32_t duty                              = 0;

static void Inf_74HC595_SendData(uint8_t data, uint8_t duty);

/**
 * @brief 初始化移位寄存器
 *
 */
void Inf_74HC595_Init(void)
{
    /* 初始化SPI */
    Driver_SPI_InitByDMA();

    /* 设置所有通道为关闭 */
    Inf_74HC595_SetAllChannel(0);
}

/**
 * @brief 设置指定通道的使能状态
 *
 * @param channel   通道号（1-8）
 * @param state     状态（0：关闭，1：使能）
 * @return Status_t
 */
Status_t Inf_74HC595_SetChannel(uint8_t channel, uint8_t state)
{
    static uint8_t outputState = 0; // 保存芯片位的当前状态

    if (channel < 1 || channel > 8) return STATUS_FAIL;

    // 计算芯片位位置
    uint8_t bitPos = (channel - 1);

    if (state) {
        outputState |= (1 << bitPos);
    }
    else {
        outputState &= ~(1 << bitPos);
    }

    // 发送所有芯片的数据
    Inf_74HC595_SendData(outputState, duty);

    return STATUS_OK;
}

/**
 * @brief 设置所有通道的使能状态
 *
 * @param state 状态（0：关闭，1：使能）
 */
void Inf_74HC595_SetAllChannel(uint8_t state)
{
    for (uint8_t i = 1; i <= 8; i++) {
        Inf_74HC595_SetChannel(i, state);
    }
}

/**
 * @brief 按照设定的占空比 使能或禁用 选择的通道
 *
 * @param useless           无用数据
 * @param channel           通道号
 * @param isComplementary   是否为互补通道
 * @param dutyCycle         占空比
 * @param isEnable          使能 or 禁用
 */
void Inf_74HC595_SetChannelDutyAndState(void *useless, uint32_t channel, bool isComplementary,
                                        uint8_t dutyCycle, bool isEnable)
{
    /* 设置占空比 */
    duty = dutyCycle;

    /* 设置通道状态 */
    Inf_74HC595_SetChannel(channel, isEnable);
}

/**
 * @brief 发送数据到移位寄存器
 *
 * @param data      待发送的数据
 * @param duty      占空比, 0~100代表 0·100的占空比
 */
static void Inf_74HC595_SendData(uint8_t data, uint8_t duty)
{
    /* 禁用DMA通道 */
    Driver_SPI_DisableDMAChannel(SPI_DMA_TX_CHANNEL);

    /* 设置数据占空比 */
    for (uint8_t i = 0; i < SHIFT_REG_DATA_SIZE; ++i) {
        if (i <= duty) {
            shiftRegData[i] = data;
        }
        else {
            shiftRegData[i] = 0;
        }
    }

    /* 设置好数据地址 */
    Driver_SPI_SendDataByDMA((uint32_t)shiftRegData, SHIFT_REG_DATA_SIZE);

    /* 使能DMA通道 */
    Driver_SPI_EnableDMAChannel(SPI_DMA_TX_CHANNEL);
}
